#include "WorkerThreadPool.h"

// 静态成员初始化
WorkerThreadPool* WorkerThreadPool::instance = nullptr;
mutex WorkerThreadPool::instanceMutex;

int Thread::generateId_ = 0;
Thread::Thread(threadFunc func)
{
    this->threadid = generateId_++;
    this->func_ = func;
}

Thread::~Thread()
{
}

int Thread::getId()
{
    return this->threadid;
}

void Thread::start()
{
    thread t(func_, threadid);
    t.detach();
}

WorkerThreadPool::WorkerThreadPool() 
    : m_initThreadSize(0), 
      m_curThreadSize(0), 
      m_idleThreadSize(0), 
      m_maxThreadSize(MAX_THREAD_SIZE), 
      taskMaxSize(MAX_TASK_SIZE),
      mode(PoolMode::MODE_FIXED),
      is_stop(true),
      taskSize_(0),
      m_initialized(false)
{
}

WorkerThreadPool::~WorkerThreadPool()
{
    is_stop = true;
    notEmpty_.notify_all();
    unique_lock<mutex> lock(taskQueMux_);
    exitcondition_.wait(lock, [&]() -> bool
                        { return threads_.size() == 0; });
}

// 获取单例实例
WorkerThreadPool* WorkerThreadPool::getInstance() {
    lock_guard<mutex> lock(instanceMutex);
    if (!instance) {
        instance = new WorkerThreadPool();
    }
    return instance;
}

// 销毁线程池
void WorkerThreadPool::destroy() {
    lock_guard<mutex> lock(instanceMutex);
    if (instance) {
        delete instance;
        instance = nullptr;
    }
}

// 初始化线程池
void WorkerThreadPool::init(int initSize) {
    if (m_initialized) {
        throw runtime_error("ThreadPool already initialized");
    }
    
    this->m_initThreadSize = initSize;
    this->is_stop = false;
    
    for (int i = 0; i < m_initThreadSize; i++) {
        // 创建线程
        auto ptr = make_unique<Thread>(bind(&WorkerThreadPool::threadFunc, this, placeholders::_1));
        // 放入map容器中
        int threadid = ptr->getId();
        threads_.emplace(make_pair(threadid, move(ptr)));
    }
    for (int i = 0; i < m_initThreadSize; i++)
    {
        threads_[i]->start();
        this->m_idleThreadSize++;
        this->m_curThreadSize++;
    }
    
    m_initialized = true;
}

void WorkerThreadPool::setMode(PoolMode mode)
{
    this->mode = mode;
}

void WorkerThreadPool::setMaxThreadSize(int size)
{
    if (!is_stop)
    {
        if (this->mode == PoolMode::MODE_FIXED)
        {
            this->m_maxThreadSize = size;
        }
    }
}

void WorkerThreadPool::setMaxTaskMaxSize(int size)
{
    if (!is_stop)
    {
        this->taskMaxSize = size;
    }
}

void WorkerThreadPool::threadFunc(int threadid)
{
    // 这里的线程函数就是从任务队列拿取任务
    // 肯定也是循环拿取，不能拿一次就不拿了
    auto lastTime = chrono::high_resolution_clock().now();
    while (!is_stop)
    {
        function<void()> task;
        {
            unique_lock<mutex> lock(taskQueMux_);
            cout << "线程 " << this_thread::get_id() << "尝试拿取任务..." << endl;
            // 这里有两个模式的判断
            while (taskQue_.size() == 0)
            {
                if (mode == PoolMode::MODE_CACHED)
                {
                    // 动态模式说明线程可能多余了，因为任务都已经没了，所以我们就按时回收线程
                    if (cv_status::timeout == notEmpty_.wait_for(lock, chrono::seconds(1)))
                    {
                        auto now = chrono::high_resolution_clock().now();
                        auto dur = chrono::duration_cast<chrono::seconds>(now - lastTime);
                        if (dur.count() > 60 && m_curThreadSize > m_initThreadSize)  // 只回收超过初始大小的线程
                        {
                            threads_.erase(threadid);
                            m_curThreadSize--;
                            m_idleThreadSize--;
                            cout << "线程 " << this_thread::get_id() << "被回收" << endl;
                            return;
                        }
                    }
                }
                else
                {
                    notEmpty_.wait(lock); // 等待队列不空
                }
                // 这里可能线程池停止了，所以要进行判断一下
                if (is_stop)
                {
                    threads_.erase(threadid);
                    m_idleThreadSize--;
                    m_curThreadSize--;
                    exitcondition_.notify_one(); // 通知主线程，避免死锁
                    cout << "线程 " << this_thread::get_id() << "退出" << endl;
                    return;
                }
            }

            // 开始拿取任务
            task = taskQue_.front();
            taskQue_.pop();
            taskSize_--;

            // 如果还有任务可以继续通知
            if (taskQue_.size() > 0)
            {
                notEmpty_.notify_one();
            }
            notFull_.notify_one();
        }

        if (task)
        {
            m_idleThreadSize--;
            task();
            m_idleThreadSize++;
        }
        lastTime = chrono::high_resolution_clock().now();
    }
    // 如果到下面来，说明线程池退出了需要优雅停止,那么该线程也需要回收
    threads_.erase(threadid);
    m_curThreadSize--;
    m_idleThreadSize--;
    exitcondition_.notify_one(); // 通知主线程，避免死锁
    cout << "线程 " << this_thread::get_id() << "退出" << endl;
}